// kilocode_change - new file
import { describe, it, expect, vi, beforeEach } from "vitest"
import * as vscode from "vscode"
import { generateTerminalCommand } from "../terminalCommandGenerator"
import { ContextProxy } from "../../core/config/ContextProxy"
import { singleCompletionHandler } from "../single-completion-handler"

vi.mock("vscode")
vi.mock("../../core/config/ContextProxy")
vi.mock("../single-completion-handler")
vi.mock("../../shared/support-prompt", () => ({
	supportPrompt: {
		create: vi.fn().mockReturnValue("mocked prompt"),
	},
}))
vi.mock("../../core/config/ProviderSettingsManager", () => ({
	ProviderSettingsManager: vi.fn().mockImplementation(() => ({
		initialize: vi.fn().mockResolvedValue(undefined),
		getProfile: vi.fn().mockResolvedValue({
			name: "test",
			apiProvider: "anthropic",
			apiKey: "test-key",
		}),
	})),
}))
vi.mock("../../i18n", () => ({
	t: vi.fn((key: string, params?: any) => {
		const translations: Record<string, string> = {
			"kilocode:terminalCommandGenerator.inputPrompt": "Kilo: Describe the command you want to generate",
			"kilocode:terminalCommandGenerator.inputPlaceholder":
				"e.g., kill the process running on port 3001, find large files, etc",
			"kilocode:terminalCommandGenerator.noActiveTerminal":
				"No active terminal found. Please open a terminal first.",
			"kilocode:terminalCommandGenerator.generatingProgress": "Generating terminal command...",
			"kilocode:terminalCommandGenerator.commandGenerated": `Generated command: ${params?.command || ""}`,
			"kilocode:terminalCommandGenerator.generationFailed": `Failed to generate command: ${params?.error || ""}`,
			"kilocode:terminalCommandGenerator.warningDialog.title": "Always Verify AI-Generated Commands",
			"kilocode:terminalCommandGenerator.warningDialog.message":
				"This command was generated by AI and may not be accurate. Terminal actions cannot be undone—once executed, changes are permanent. Running unverified commands can result in irreversible data loss, security issues, or system damage. Review and understand the command completely before proceeding!",
			"kilocode:terminalCommandGenerator.warningDialog.okButton": "OK, I Understand",
			"kilocode:terminalCommandGenerator.warningDialog.cancelButton": "Cancel",
		}
		return translations[key] || key
	}),
}))

describe("generateTerminalCommand", () => {
	const mockOutputChannel = {
		appendLine: vi.fn(),
	} as unknown as vscode.OutputChannel

	const mockContext = {
		subscriptions: [],
		workspaceState: {
			get: vi.fn(),
		},
		globalState: {
			get: vi.fn(),
			update: vi.fn().mockResolvedValue(undefined),
		},
	} as unknown as vscode.ExtensionContext

	const mockTerminal = {
		sendText: vi.fn(),
		show: vi.fn(),
		shellIntegration: {
			cwd: {
				fsPath: "/test/path",
			},
		},
	} as unknown as vscode.Terminal

	beforeEach(() => {
		vi.clearAllMocks()

		const mockContextProxy = {
			getProviderSettings: vi.fn().mockReturnValue({
				apiProvider: "anthropic",
				apiKey: "test-key",
			}),
			getValue: vi.fn().mockReturnValue(null),
		}
		Object.defineProperty(ContextProxy, "instance", {
			get: vi.fn(() => mockContextProxy),
			configurable: true,
		})

		vscode.window.showInputBox = vi.fn().mockResolvedValue("list files")
		Object.defineProperty(vscode.window, "activeTerminal", {
			get: vi.fn(() => mockTerminal),
			configurable: true,
		})
		vscode.window.withProgress = vi.fn().mockImplementation(async (options, callback) => {
			const mockProgress = { report: vi.fn() }
			return await callback(mockProgress as any, {} as any)
		})
		vscode.window.showInformationMessage = vi.fn().mockResolvedValue(undefined)
		vscode.window.showErrorMessage = vi.fn().mockResolvedValue(undefined)

		// Mock ProgressLocation enum
		Object.defineProperty(vscode, "ProgressLocation", {
			value: {
				Notification: 15,
				Window: 10,
				SourceControl: 1,
			},
			configurable: true,
		})

		vi.mocked(singleCompletionHandler).mockResolvedValue("ls -la")
	})

	it("should generate and place terminal command without executing", async () => {
		// Mock returning user (warning already acknowledged)
		vi.mocked(mockContext.globalState.get).mockReturnValue(true)

		await generateTerminalCommand({
			outputChannel: mockOutputChannel,
			context: mockContext,
		})

		expect(vscode.window.showInputBox).toHaveBeenCalledWith({
			prompt: "Kilo: Describe the command you want to generate",
			placeHolder: "e.g., kill the process running on port 3001, find large files, etc",
			ignoreFocusOut: true,
		})

		expect(singleCompletionHandler).toHaveBeenCalled()
		expect(mockTerminal.sendText).toHaveBeenCalledWith("ls -la", false)
		expect(mockTerminal.show).toHaveBeenCalled()
		expect(vscode.window.showInformationMessage).toHaveBeenCalledWith("Generated command: ls -la")
	})

	it("should handle user cancellation", async () => {
		// Mock returning user (warning already acknowledged)
		vi.mocked(mockContext.globalState.get).mockReturnValue(true)
		vscode.window.showInputBox = vi.fn().mockResolvedValue(undefined)

		await generateTerminalCommand({
			outputChannel: mockOutputChannel,
			context: mockContext,
		})

		expect(singleCompletionHandler).not.toHaveBeenCalled()
		expect(mockTerminal.sendText).not.toHaveBeenCalled()
	})

	it("should handle missing active terminal", async () => {
		// Mock returning user (warning already acknowledged)
		vi.mocked(mockContext.globalState.get).mockReturnValue(true)
		Object.defineProperty(vscode.window, "activeTerminal", {
			get: vi.fn(() => undefined),
			configurable: true,
		})

		await generateTerminalCommand({
			outputChannel: mockOutputChannel,
			context: mockContext,
		})

		expect(vscode.window.showErrorMessage).toHaveBeenCalledWith(
			"No active terminal found. Please open a terminal first.",
		)
		expect(singleCompletionHandler).not.toHaveBeenCalled()
	})

	it("should handle API configuration errors", async () => {
		// Mock returning user (warning already acknowledged)
		vi.mocked(mockContext.globalState.get).mockReturnValue(true)
		const mockContextProxy = {
			getProviderSettings: vi.fn().mockReturnValue(null),
			getValue: vi.fn().mockReturnValue([]),
		}
		Object.defineProperty(ContextProxy, "instance", {
			get: vi.fn(() => mockContextProxy),
			configurable: true,
		})

		await generateTerminalCommand({
			outputChannel: mockOutputChannel,
			context: mockContext,
		})

		expect(vscode.window.showErrorMessage).toHaveBeenCalledWith(
			expect.stringContaining("Failed to generate command:"),
		)
	})

	describe("warning dialog functionality", () => {
		it("should show warning dialog on first use", async () => {
			// Mock first-time user (warning not acknowledged)
			vi.mocked(mockContext.globalState.get).mockReturnValue(false)
			vscode.window.showInformationMessage = vi.fn().mockResolvedValue("OK, I Understand")

			await generateTerminalCommand({
				outputChannel: mockOutputChannel,
				context: mockContext,
			})

			expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(
				expect.stringContaining("Always Verify AI-Generated Commands"),
				expect.objectContaining({ modal: true }),
				"OK, I Understand",
				"Cancel",
			)
			expect(mockContext.globalState.update).toHaveBeenCalledWith("terminalCommandWarningAcknowledged", true)
			expect(mockTerminal.sendText).toHaveBeenCalledWith("ls -la", false)
		})

		it("should not show warning dialog if already acknowledged", async () => {
			// Mock returning user (warning already acknowledged)
			vi.mocked(mockContext.globalState.get).mockReturnValue(true)

			await generateTerminalCommand({
				outputChannel: mockOutputChannel,
				context: mockContext,
			})

			expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1) // Only the success message
			expect(vscode.window.showInformationMessage).toHaveBeenCalledWith("Generated command: ls -la")
			expect(mockContext.globalState.update).not.toHaveBeenCalledWith("terminalCommandWarningAcknowledged", true)
			expect(mockTerminal.sendText).toHaveBeenCalledWith("ls -la", false)
		})

		it("should abort command generation if user cancels warning dialog", async () => {
			// Mock first-time user who cancels the warning
			vi.mocked(mockContext.globalState.get).mockReturnValue(false)
			vscode.window.showInformationMessage = vi.fn().mockResolvedValue("Cancel")

			await generateTerminalCommand({
				outputChannel: mockOutputChannel,
				context: mockContext,
			})

			expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(
				expect.stringContaining("Always Verify AI-Generated Commands"),
				expect.objectContaining({ modal: true }),
				"OK, I Understand",
				"Cancel",
			)
			expect(mockContext.globalState.update).not.toHaveBeenCalledWith("terminalCommandWarningAcknowledged", true)
			expect(vscode.window.showInputBox).not.toHaveBeenCalled()
			expect(mockTerminal.sendText).not.toHaveBeenCalled()
		})

		it("should abort command generation if user dismisses warning dialog", async () => {
			// Mock first-time user who dismisses the warning (returns undefined)
			vi.mocked(mockContext.globalState.get).mockReturnValue(false)
			vscode.window.showInformationMessage = vi.fn().mockResolvedValue(undefined)

			await generateTerminalCommand({
				outputChannel: mockOutputChannel,
				context: mockContext,
			})

			expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(
				expect.stringContaining("Always Verify AI-Generated Commands"),
				expect.objectContaining({ modal: true }),
				"OK, I Understand",
				"Cancel",
			)
			expect(mockContext.globalState.update).not.toHaveBeenCalledWith("terminalCommandWarningAcknowledged", true)
			expect(vscode.window.showInputBox).not.toHaveBeenCalled()
			expect(mockTerminal.sendText).not.toHaveBeenCalled()
		})

		it("should handle globalState.get returning undefined (first-time user)", async () => {
			// Mock globalState.get returning undefined (equivalent to false for first-time user)
			vi.mocked(mockContext.globalState.get).mockReturnValue(undefined)
			vscode.window.showInformationMessage = vi.fn().mockResolvedValue("OK, I Understand")

			await generateTerminalCommand({
				outputChannel: mockOutputChannel,
				context: mockContext,
			})

			expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(
				expect.stringContaining("Always Verify AI-Generated Commands"),
				expect.objectContaining({ modal: true }),
				"OK, I Understand",
				"Cancel",
			)
			expect(mockContext.globalState.update).toHaveBeenCalledWith("terminalCommandWarningAcknowledged", true)
		})
	})
})
